%% Copyright (C) 2008, changgb
%% File    : nbstore.erl
%% Author  : changgb (changgb@hotmail.com)
%% Last modified: 2008-5-24

-module(nbstore).
-define(ADAPTER_MODULE, nbbuffer).
%%-define(ADAPTER_MODULE, nbdisk).

%% 时间0点
-define(TIME_ZERO, {1210,768810,468000}).
%
%%
%% Include files
%%

%%
%% Exported Functions
%%
-export([del_data/1, put_data/2, put_data/3, put_data/4, get_data/1, get_data/2, incr_data/2, stop/0, start/0]).
-export([get_state/1]).
%%
%% API Functions
%%


start() -> 
	?ADAPTER_MODULE:start(),    
	ok.

stop() -> 
	?ADAPTER_MODULE:stop(), 
	ok.

get_state(all)->
	?ADAPTER_MODULE:get_state(all);
get_state(Name)->
	?ADAPTER_MODULE:get_state(Name).

%%
%% ok | {error, Reason}
%%
del_data(Key) -> 
	?ADAPTER_MODULE:delete(Key).
		
%%
%% ok | {error, Reason}
%%
put_data(Key, Value) ->
	put_data(Key, Value, 0, null).

put_data(Key, Value, ExpireTime) ->
	put_data(Key, Value, ExpireTime, null).

%% 如果 Etag 为null 生成新 Etag
put_data(Key, Value, ExpireTime, Etag) when (Etag == null) ->
    NewTag = nbutil:md5(Value),
    put_data(Key, Value, ExpireTime, NewTag);
put_data(Key, Value, ExpireTime, Etag)->
    case ExpireTime > 0 of
        true ->
            Diff = timer:now_diff(erlang:now(), ?TIME_ZERO) + ExpireTime * 1000000,
            ?ADAPTER_MODULE:insert(Key, Value, {Diff, Etag});
        false->
            ?ADAPTER_MODULE:insert(Key, Value, {0, Etag}) 
    end.

%%
%% null | not_modified | {ok, {Value, Etag}} | {error, Reason}
%%
get_data(Key) ->
	get_data(Key, null).

get_data(Key, Etag) ->
    case ?ADAPTER_MODULE:select_ext(Key) of
        null ->
            null;
        {ExpireTime, OldEtag} ->
            case ExpireTime == 0 of
                true ->
                    
                    get_data(Key, Etag, 0, 0, OldEtag);
                false ->
                    %%当前局元时,间隔多长时间
                    NowDiff = timer:now_diff(erlang:now(), ?TIME_ZERO),
                    get_data(Key, Etag, NowDiff, ExpireTime, OldEtag)
            end
    end.

%% 验证过期时间
get_data(Key, _Etag, NowDiff, ExpireTime, _OldEtag) when (ExpireTime > 0) and ( NowDiff > ExpireTime) ->
    %% 已过期
    ?ADAPTER_MODULE:delete(Key),
    null;
%% 验证TAG
get_data(_Key, Etag, _NowDiff, _ExpireTime, OldEtag) when (Etag =/= null) and (Etag == OldEtag) ->
    %% 未过期
    not_modified;
get_data(Key, _Etag, _NowDiff, _ExpireTime, OldEtag)->        
    case ?ADAPTER_MODULE:select(Key) of
        null ->
            null;
        Value ->
            {ok, {Value, OldEtag}}
    end.

%% {ok, N} -n , n
incr_data(Key, Incr)->
    {ok, ?ADAPTER_MODULE:incr(Key, Incr)}.
